parser grammar Sintactico;

options {
  language = Java;
  tokenVocab = Lexico;
}

@header {
  package practica5;
}

@members {
     private ArrayList<RecognitionException> errors = new ArrayList<RecognitionException>();
     public ArrayList<RecognitionException> getErrors() {
        return errors;
     }
     @Override
     public void reportError (RecognitionException e) {
        String msg = getErrorMessage(e, getTokenNames());
        System.err.println(msg);
        errors.add(e);
     }
}



entrada: (primerbloque segundobloque tercerbloque?);

primerbloque: macros macros declaracion;

segundobloque: NUEVOBLOQUE regla1 regla2;

tercerbloque: NUEVOBLOQUE funcion principal;

tipo: INT|CHAR|VOID;

///////////////////
////PRIMER BLOQUE//
///////////////////
macros: IDENT CORCHETES;
declaracion: PORCENTAJE LLAVE_A
             variable
             variable
             PORCENTAJE LLAVE_C;
variable: tipo IDENT PUNTO_COMA;



////////////////////
////SEGUNDO BLOQUE//
////////////////////
regla1: patron1 accion PUNTO_COMA;
patron1: LLAVE_A IDENT LLAVE_C PARENTESIS_A LLAVE_A IDENT LLAVE_C OR LLAVE_A IDENT LLAVE_C PARENTESIS_C ASTERISCO;
regla2: patron2 accion PUNTO_COMA;
patron2: LLAVE_A IDENT LLAVE_C SUMA;
accion: IDENT (INCREMENTO);



///////////////////
////TERCER BLOQUE//
///////////////////
funcion: tipo IDENT PARENTESIS_A VOID PARENTESIS_C LLAVE_A cuerpo_funcion LLAVE_C;
cuerpo_funcion: ret;

principal: tipo MAIN PARENTESIS_A parametros PARENTESIS_C LLAVE_A cuerpo_main LLAVE_C;

parametros: par1 COMA par2;
par1: tipo IDENT;
par2: tipo ASTERISCO IDENT CORCHETES;

cuerpo_main: asignacion_funcion asignacion_valor asignacion_valor llamada_funcion llamada_funcion imprimir imprimir ret;

asignacion_funcion: IDENT IGUAL IDENT PARENTESIS_A params PARENTESIS_C PUNTO_COMA;
params: param1 COMA param2;
param1: IDENT CORCHETES;
param2: CADENA;

asignacion_valor: IDENT IGUAL NUMERO PUNTO_COMA;
llamada_funcion: IDENT PARENTESIS_A IDENT? PARENTESIS_C PUNTO_COMA;
imprimir: PRINTF PARENTESIS_A CADENA COMA IDENT PARENTESIS_C PUNTO_COMA;

ret: RET NUMERO PUNTO_COMA;

//primerbloque: macros*
//              declaracion;
//              
//segundobloque: NUEVOBLOQUE
//               (reglas)+;
//               
//tercerbloque: NUEVOBLOQUE
//              funciones*
//              principal;
//
//
///////////////////
////PRIMER BLOQUE//
///////////////////
//macros: IDENT
//        CORCHETES;
//declaracion: PORCENTAJE LLAVE_A
//             (variable)+
//             PORCENTAJE LLAVE_C;
//variable: tipo IDENT PUNTO_COMA;
//
//
////////////////////
////SEGUNDO BLOQUE//
////////////////////
//reglas: patron accion PUNTO_COMA;
//patron: LLAVE_A IDENT LLAVE_C (SUMA|ASTERISCO)? (PARENTESIS_A LLAVE_A IDENT LLAVE_C (OR LLAVE_A IDENT LLAVE_C)* PARENTESIS_C (ASTERISCO|SUMA))?;
//accion: IDENT (INCREMENTO|DECREMENTO);
//
//
///////////////////
////TERCER BLOQUE//
///////////////////
//funciones: tipo IDENT PARENTESIS_A parametros PARENTESIS_C LLAVE_A cuerpo LLAVE_C;
//principal: tipo MAIN PARENTESIS_A parametros PARENTESIS_C LLAVE_A cuerpo LLAVE_C;
//parametros: ((VOID)? | tipo parametro (COMA tipo parametro)*);
//cuerpo: ((asignacion|imprimir|llamada_funcion) PUNTO_COMA)* ret;
//asignacion: IDENT IGUAL (parametro|llamada_funcion);
//llamada_funcion: IDENT PARENTESIS_A (parametro (COMA parametro)*)? PARENTESIS_C;
//imprimir: PRINTF PARENTESIS_A CADENA COMA IDENT PARENTESIS_C;
//ret: RET NUMERO? PUNTO_COMA;
//
//parametro: (ASTERISCO? IDENT CORCHETES*) | CADENA | NUMERO;
//
//tipo: INT|CHAR|VOID;